/**
 * @file    VMII_rs485.c
 * @brief   南京欧陆-VMII
 * @author  Liuwei
 * @version 1.0.1
 * @date    2024-11-06
 *          VMII系列离网储能逆变器MODBUS-RTU通信协议_20220712(1).pdf
 * @copyright Copyright (c) 2023 JBD-Energy Storage Technology Co. LTD
 * 
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version   <th>Author   <th>Description
 * <tr><td>2024-11-06 <td>1.0.1     <td>Liuwei   <td>首次创建
 * </table>
 */

/* includes ------------------------------------------------------------------*/
#include "vmii_rs485.h"
#include "modbus_app.h"
#include "if_di.h"
#include "cfg_prj.h"
#include "sample.h"
#include "parallel_com.h"
#include "var_mng.h"
#include "param_mng.h"
/* macro/define --------------------------------------------------------------*/

/* typedef -------------------------------------------------------------------*/
#define CMD_READ_IN_REG        (0x03)

#define INPUT_REG_ST           (200)
#define INPUT_REG_END          (215) 
#define INTPUT_REG_SIZE        (16)
/* local functions -----------------------------------------------------------*/
static void vmii_read_input_reg(md_data_type md_data_msg , uint8_t *tx_buf ,uint16_t *tx_len);
static void vmii_update_input_buf(void);
static uint16_t get_sys_state(void);
static uint16_t get_prp_state(void);
static uint16_t get_fault_state(void);
/* static variables ----------------------------------------------------------*/
static uint16_t input_reg_buf[INTPUT_REG_SIZE] = {0};

/* global variables ----------------------------------------------------------*/

/** ------------------------------------------------------------------------- *
  *                             Global function
 ** ------------------------------------------------------------------------- */
uint8_t vmii_rs485_analysis(uint8_t *rx_buf , uint16_t rx_len ,uint8_t *tx_buf , uint16_t *tx_len)
{
    md_data_type recv_md_data = {0};
    if(TRUE == modbus_rtu_analysis(rx_buf , rx_len , &recv_md_data))
    {
        if(1 == recv_md_data.addr)
        {
            if((recv_md_data.reg_addr >= INPUT_REG_ST)
              && (recv_md_data.reg_addr + recv_md_data.data_len <= INPUT_REG_END)
              && (CMD_READ_IN_REG == recv_md_data.cmd_code))
            {
                vmii_update_input_buf();
                vmii_read_input_reg(recv_md_data , tx_buf , tx_len);
                return TRUE;
            }
            return FALSE;
        }
        return FALSE;
    }
    return FALSE;
}

/** ------------------------------------------------------------------------- *
  *                              Local function
 ** ------------------------------------------------------------------------- */
static void vmii_read_input_reg(md_data_type md_data_msg, uint8_t *tx_buf, uint16_t *tx_len) 
{
    uint16_t data_len = 0;
    uint16_t crc_code = 0;
    uint8_t i = 0;
    uint8_t *p_tx = tx_buf;
	uint16_t idx_cnt = 0;
	uint16_t start_addr = 0;

    p_tx[idx_cnt ++] = md_data_msg.addr;
    p_tx[idx_cnt ++] = md_data_msg.cmd_code;
    data_len = md_data_msg.data_len * 2;
    p_tx[idx_cnt ++] = data_len;
    
	start_addr = md_data_msg.reg_addr - INPUT_REG_ST;
    for (i = 0; i < md_data_msg.data_len; ++i) 
	{
        p_tx[idx_cnt ++] = input_reg_buf[i + start_addr] >> 8;
		p_tx[idx_cnt ++] = input_reg_buf[i + start_addr];
    }

    crc_code = modbus_calc_crc(tx_buf, idx_cnt);

    p_tx[idx_cnt ++] = crc_code & 0xff;
    p_tx[idx_cnt ++] = crc_code >> 8;

    *tx_len = idx_cnt;   //修改
}

static void vmii_update_input_buf(void)
{
    int16_t sys_curr = 0;
    uint8_t i = 0;

    input_reg_buf[0x00] = 0x6A62;
    input_reg_buf[0x01] = master_data_reg.total_full_cap * 51.2 * 0.0001;
    input_reg_buf[0x02] = master_data_reg.avg_batt_volt * 0.1;
	sys_curr = master_data_reg.total_bus_curr * 0.1;
    input_reg_buf[0x03] = sys_curr;
	input_reg_buf[0x04] = master_data_reg.avg_max_temp - 2731;
	input_reg_buf[0x05] = master_data_reg.avg_soc;
    input_reg_buf[0x06] = master_data_reg.avg_soh;
	input_reg_buf[0x07] = var_get_data(VAR_ID_TP_SOP_CV);
	input_reg_buf[0x08] = var_get_data(VAR_ID_TP_SOP_CC);
	input_reg_buf[0x09] = var_get_data(VAR_ID_TP_SOP_DV);
	input_reg_buf[0x0A] = var_get_data(VAR_ID_TP_SOP_DC);
	
	input_reg_buf[0x0B] = get_sys_state();
	input_reg_buf[0x0C] = get_prp_state();
	input_reg_buf[0x0D] = get_fault_state();
}

static uint16_t get_sys_state(void)
{
	uint16_t sys_state = 0;
	
	if(var_get_data(VAR_ID_TP_SOP_CC) > 0)
		sys_state |= (1 << 0);
	if(var_get_data(VAR_ID_TP_SOP_DC) > 0)
		sys_state |= (1 << 1);
	if(parallel_get_pcs_ctrl(PARALLEL_PCS_FROCE_CHG1) == TRUE)
		sys_state |= (1 << 2);
	if(parallel_get_pcs_ctrl(PARALLEL_PCS_FROCE_CHG2) == TRUE)
		sys_state |= (1 << 3);
	if(diag_get_prp(PRP_ID_FULL_CHG))
		sys_state |= (1 << 4);
	
	return sys_state;
}


static uint16_t get_prp_state(void)
{
	uint16_t prp_msg = 0;
	
	if(master_data_reg.total_prp_msg.bit.occ || master_data_reg.total_prp_msg.bit.occ2)
		prp_msg |= (1 << 5);
	if(master_data_reg.total_prp_msg.bit.ocd || master_data_reg.total_prp_msg.bit.ocd2)
		prp_msg |= (1 << 0);
	if(master_data_reg.total_prp_msg.bit.otc || master_data_reg.total_prp_msg.bit.otd)
		prp_msg |= (1 << 2);
	if(master_data_reg.total_prp_msg.bit.utc || master_data_reg.total_prp_msg.bit.utd)
		prp_msg |= (1 << 1);
	if(master_data_reg.total_prp_msg.bit.col 
		|| master_data_reg.total_prp_msg.bit.tol 
		|| master_data_reg.total_prp_msg.bit.afe_err
		|| master_data_reg.total_prp_msg.bit.fcmos
		|| master_data_reg.total_prp_msg.bit.fdmos)
		prp_msg |= (1 << 6);
	
	return prp_msg;
}

static uint16_t get_fault_state(void)
{
	uint16_t ft_state = 0;
	
	if(master_data_reg.total_prp_msg.bit.fcmos)
		ft_state |= (1 << 0);
	if(master_data_reg.total_prp_msg.bit.fdmos)
		ft_state |= (1 << 1);
	if(master_data_reg.total_prp_msg.bit.tol)
		ft_state |= (1 << 2);
	if(master_data_reg.total_prp_msg.bit.col)
		ft_state |= (1 << 4);
	if(master_data_reg.total_prp_msg.bit.afe_err)
		ft_state |= (1 << 5);
	
	return ft_state;
}
/********** Copyright (c) 2023 JBD-Energy Storage Technology Co. LTD *********/
